#ifndef UNDOREDOMANAGER_H
#define UNDOREDOMANAGER_H

#include <QObject>
#include <QUndoStack>
#include <QVariant>
#include <QString>
#include <functional>
#include <QMap>
#include "ImageOperation.h"

/**
 * @brief 撤销/重做管理器类
 * 使用Qt的QUndoStack实现撤销/重做功能
 */
class UndoRedoManager : public QObject
{
    Q_OBJECT
public:
    explicit UndoRedoManager(QObject *parent = nullptr);
    ~UndoRedoManager();
    
    /**
     * @brief 添加一个可撤销操作到历史记录
     * @param operationInfo 操作信息
     */
    void addOperation(const OperationInfo& operationInfo);
    
    /**
     * @brief 撤销指定图像的上一步操作
     * @param imageGuid 图像GUID
     * @param operationType 输出参数，用于返回操作类型
     * @param operationDescription 输出参数，用于返回操作描述
     * @return 是否撤销成功
     */
    bool undo(const QString& imageGuid, ImageOperationType* operationType = nullptr, QString* operationDescription = nullptr);
    
    /**
     * @brief 重做指定图像的上一步撤销操作
     * @param imageGuid 图像GUID
     * @param operationType 输出参数，用于返回操作类型
     * @param operationDescription 输出参数，用于返回操作描述
     * @return 是否重做成功
     */
    bool redo(const QString& imageGuid, ImageOperationType* operationType = nullptr, QString* operationDescription = nullptr);
    
    /**
     * @brief 清空所有撤销和重做历史
     */
    void clearHistory();
    
    /**
     * @brief 清空指定图像的撤销和重做历史
     * @param imageGuid 图像GUID
     */
    void clearHistory(const QString& imageGuid);
    
    /**
     * @brief 检查是否可以对指定图像执行撤销操作
     * @param imageGuid 图像GUID
     * @return 是否可以撤销
     */
    bool canUndo(const QString& imageGuid) const;
    
    /**
     * @brief 检查是否可以对指定图像执行重做操作
     * @param imageGuid 图像GUID
     * @return 是否可以重做
     */
    bool canRedo(const QString& imageGuid) const;
    
    /**
     * @brief 获取指定图像当前可以撤销的操作描述
     * @param imageGuid 图像GUID
     * @return 操作描述字符串，如果没有可撤销操作则返回空字符串
     */
    QString getUndoDescription(const QString& imageGuid) const;
    
    /**
     * @brief 获取指定图像当前可以重做的操作描述
     * @param imageGuid 图像GUID
     * @return 操作描述字符串，如果没有可重做操作则返回空字符串
     */
    QString getRedoDescription(const QString& imageGuid) const;
    
    /**
     * @brief 获取当前可执行操作（undo或redo）的值
     * 用于直接获取操作的值，不需要返回已经通过其他方式获取的操作类型和描述
     * @param imageGuid 图像GUID
     * @return 操作的值，如果没有可执行操作则返回无效的QVariant
     */
    QVariant getCurrentOperationValue(const QString& imageGuid) const;
    
    /**
     * @brief 设置最大历史记录数量
     * @param maxSize 最大历史记录数量
     */
    void setMaxHistorySize(int maxSize);
    
    /**
     * @brief 获取最大历史记录数量
     * @return 最大历史记录数量
     */
    int getMaxHistorySize() const;
    
    /**
     * @brief 获取指定图像的撤销栈大小
     * @param imageGuid 图像GUID
     * @return 撤销栈中的操作数量
     */
    int getUndoStackSize(const QString& imageGuid) const;
    
    /**
     * @brief 创建临时目录
     * 确保软件运行目录下的temp文件夹存在
     * @return 临时目录路径，如果创建失败则返回空字符串
     */
    QString createTempDirectory();
    
    /**
     * @brief 暂停记录操作历史
     * 暂停后，所有新的操作将不会被添加到历史记录中
     */
    void pauseHistory();
    
    /**
     * @brief 恢复记录操作历史
     */
    void resumeHistory();
    
    /**
     * @brief 检查是否暂停记录操作历史
     * @return 是否暂停
     */
    bool isHistoryPaused() const;

    /**
     * @brief 将多个操作合并为一个复合操作
     * 用于需要将多个步骤合并为一个撤销/重做单元的场景
     * @param operationsInfo 操作信息列表
     * @param description 复合操作的描述
     */
    void addCompositeOperation(
            const QList<OperationInfo>& operationsInfo,
            const QString& description = "");

signals:
    /**
     * @brief 当撤销/重做状态改变时发出的信号
     * @param imageGuid 图像GUID
     * @param canUndo 当前是否可以撤销
     * @param canRedo 当前是否可以重做
     */
    void undoRedoStateChanged(const QString& imageGuid, bool canUndo, bool canRedo);
    
    /**
     * @brief 当历史记录被清空时发出的信号
     */
    void historyCleared();
    
    /**
     * @brief 当一个操作被撤销时发出的信号
     * @param operation 被撤销的操作
     */
    void operationUndone(QUndoCommand *operation);
    
    /**
     * @brief 当一个操作被重做时发出的信号
     * @param operation 被重做的操作
     */
    void operationRedone(QUndoCommand *operation);
    
    /**
     * @brief 当一个新操作被添加到历史记录时发出的信号
     * @param operation 新添加的操作
     */
    void operationAdded(QUndoCommand *operation);



private:
    // 每个图像的撤销栈映射
    QMap<QString, QUndoStack*> m_undoStacks;
    
    // 最大历史记录数量
    int m_maxHistorySize;
    
    // 是否暂停记录操作历史
    bool m_isHistoryPaused;
    
    // 临时目录路径
    QString m_tempDirectoryPath;
    
    // 获取指定图像的撤销栈，如果不存在则创建
    QUndoStack* getOrCreateUndoStack(const QString& imageGuid);
    

};

#endif // UNDOREDOMANAGER_H
